﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Ex03.GarageLogic
{
    public class VehicleFactory
    {
        public enum eVehicleType
        {
            FuelMotorbike = 1,
            ElectricMotorbike,
            FuelCar,
            ElectricCar,
            Bus
        }

        public static List<string> GetPropertiesOfVehicleType(eVehicleType i_VehicleType)
        {
            List<string> properties = new List<string>();

            properties.Add("Model Name");

            switch (i_VehicleType)
            {
                case eVehicleType.FuelMotorbike:
                    properties.Add("License Type");
                    properties.Add("Engine Volume");

                    break;
                case eVehicleType.ElectricMotorbike:
                    properties.Add("License Type");
                    properties.Add("Engine Volume");

                    break;
                case eVehicleType.FuelCar:
                    properties.Add("Car Color");
                    properties.Add("Number Of Doors");

                    break;
                case eVehicleType.ElectricCar:
                    properties.Add("Car Color");
                    properties.Add("Number Of Doors");

                    break;
                case eVehicleType.Bus:
                    properties.Add("Maximal Allowed Number Of Passengers");
                    properties.Add("Guide Seat Exists");

                    break;
            }

            return properties;
        }

        public static Vehicle CreateVehicle(eVehicleType i_VehicleType, Dictionary<string, string> i_VehicleProperties)
        {
            Vehicle retVal = null;

            switch (i_VehicleType)
            {
                case eVehicleType.FuelMotorbike:
                    retVal = createFuelMotorbike(i_VehicleProperties);
                    break;

                case eVehicleType.ElectricMotorbike:
                    retVal = createElectricMotorbike(i_VehicleProperties);
                    break;

                case eVehicleType.FuelCar:
                    retVal = createFuelCar(i_VehicleProperties);
                    break;

                case eVehicleType.ElectricCar:
                    retVal = createElectricCar(i_VehicleProperties);
                    break;

                case eVehicleType.Bus:
                    retVal = createBus(i_VehicleProperties);
                    break;
            }

            return retVal;
        }

        private static Vehicle createFuelMotorbike(Dictionary<string, string> i_VehicleProperties)
        {
            Vehicle retVal = null;
            eLicenseType licenseType;
            bool parsingSuccess;
            int engineVolume;
            const bool v_IgnoreCase = true;

            licenseType =
                (eLicenseType)Enum.Parse(typeof(eLicenseType), i_VehicleProperties["License Type"], v_IgnoreCase);
            parsingSuccess = int.TryParse(i_VehicleProperties["Engine Volume"], out engineVolume);

            if (!parsingSuccess)
            {
                throw new FormatException();
            }

            retVal = new FuelMotorbike(
                i_VehicleProperties["Model Name"],
                UniqueLicenseNumberGenerator.GenerateUniqueLicenseNumber(),
                createWheels(2, 31),
                eFuelType.Octan98,
                6,
                licenseType,
                engineVolume);

            return retVal;
        }

        private static Vehicle createElectricMotorbike(Dictionary<string, string> i_VehicleProperties)
        {
            Vehicle retVal = null;
            eLicenseType licenseType;
            bool parsingSuccess;
            int engineVolume;
            const bool v_IgnoreCase = true;

            licenseType =
                (eLicenseType)Enum.Parse(typeof(eLicenseType), i_VehicleProperties["License Type"], v_IgnoreCase);
            parsingSuccess = int.TryParse(i_VehicleProperties["Engine Volume"], out engineVolume);

            if (!parsingSuccess)
            {
                throw new FormatException();
            }

            retVal = new ElectricMotorbike(
                i_VehicleProperties["Model Name"],
                UniqueLicenseNumberGenerator.GenerateUniqueLicenseNumber(),
                createWheels(2, 31),
                2.5f,
                licenseType,
                engineVolume);

            return retVal;
        }

        private static Vehicle createFuelCar(Dictionary<string, string> i_VehicleProperties)
        {
            Vehicle retVal = null;
            eColor carColor;
            eDoorsCount doorsCount;
            const bool v_IgnoreCase = true;

            carColor =
                (eColor)Enum.Parse(typeof(eColor), i_VehicleProperties["Car Color"], v_IgnoreCase);

            switch (i_VehicleProperties["Number Of Doors"])
            {
                case "2":
                    doorsCount = eDoorsCount.Two;
                    break;

                case "3":
                    doorsCount = eDoorsCount.Three;
                    break;

                case "4":
                    doorsCount = eDoorsCount.Four;
                    break;

                case "5":
                    doorsCount = eDoorsCount.Five;
                    break;

                default:
                    throw new FormatException();
            }

            retVal = new FuelCar(
                i_VehicleProperties["Model Name"],
                UniqueLicenseNumberGenerator.GenerateUniqueLicenseNumber(),
                createWheels(4, 29),
                eFuelType.Octan95,
                45,
                carColor,
                doorsCount);

            return retVal;
        }

        private static Vehicle createElectricCar(Dictionary<string, string> i_VehicleProperties)
        {
            Vehicle retVal = null;
            eColor carColor;
            eDoorsCount doorsCount;
            const bool v_IgnoreCase = true;

            carColor =
                (eColor)Enum.Parse(typeof(eColor), i_VehicleProperties["Car Color"], v_IgnoreCase);

            switch (i_VehicleProperties["Number Of Doors"])
            {
                case "2":
                    doorsCount = eDoorsCount.Two;
                    break;

                case "3":
                    doorsCount = eDoorsCount.Three;
                    break;

                case "4":
                    doorsCount = eDoorsCount.Four;
                    break;

                case "5":
                    doorsCount = eDoorsCount.Five;
                    break;

                default:
                    throw new FormatException();
            }

            retVal = new ElectricCar(
                i_VehicleProperties["Model Name"],
                UniqueLicenseNumberGenerator.GenerateUniqueLicenseNumber(),
                createWheels(4, 29),
                2.5f,
                carColor,
                doorsCount);

            return retVal;
        }

        private static Vehicle createBus(Dictionary<string, string> i_VehicleProperties)
        {
            Vehicle retVal = null;
            bool parsingSuccess;
            bool guideSeatExists;
            int maxNumberOfPassengersAllowed;
            
            if (i_VehicleProperties["Guide Seat Exists"].ToLowerInvariant() != "yes" &&
                i_VehicleProperties["Guide Seat Exists"].ToLowerInvariant() != "no")
            {
                throw new FormatException("Guide Seat Exists property may contain only 'Yes' or 'No'.");
            }

            guideSeatExists = i_VehicleProperties["Guide Seat Exists"].ToLowerInvariant() == "yes";

            parsingSuccess =
                int.TryParse(i_VehicleProperties["Maximal Allowed Number Of Passengers"], out maxNumberOfPassengersAllowed);

            if (!parsingSuccess)
            {
                throw new FormatException();
            }

            retVal = new FuelBus(
                       i_VehicleProperties["Model Name"],
                       UniqueLicenseNumberGenerator.GenerateUniqueLicenseNumber(),
                       createWheels(8, 25),
                       eFuelType.Soler,
                       200,
                       maxNumberOfPassengersAllowed,
                       guideSeatExists);

            return retVal;
        }

        private static List<Wheel> createWheels(int i_NumberOfWheels, float i_MaximalAirPressure)
        {
            List<Wheel> wheels = new List<Wheel>();
            
            for(int i = 0; i < i_NumberOfWheels; i++)
            {
                wheels.Add(new Wheel("Michelin", i_MaximalAirPressure));
            }

            return wheels;
        }
    }
}
